package com.ejlchina.tool.fragment

import android.annotation.SuppressLint
import android.bluetooth.BluetoothGattCharacteristic
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.adolf.androiddemo.R
import com.adolf.androiddemo.databinding.DialogIndexFixSelectIndexBinding
import com.adolf.androiddemo.databinding.FragmentIndexFixBinding
import com.ejlchina.tool.MainActivity
import com.ejlchina.tool.adapter.BucketIndexAdapter
import com.ejlchina.tool.adapter.IndexFixDialogAdapter
import com.ejlchina.tool.base.BaseBindingFragment2
import com.ejlchina.tool.bean.BleDeviceBean
import com.ejlchina.tool.constant.COMMAND_DELAY_TIME_300
import com.ejlchina.tool.constant.INDEX_FIX_URL
import com.ejlchina.tool.enums.SuccessFailEnum
import com.ejlchina.tool.extension.safeNavigate
import com.ejlchina.tool.network.BucketIndexInfo
import com.ejlchina.tool.singleton.GlobalConnectObject
import com.ejlchina.tool.util.COMMAND_485_SLAVE_GET_DOWNLOAD
import com.ejlchina.tool.util.COMMAND_485_SLAVE_GET_UPWARD
import com.ejlchina.tool.util.COMMAND_485_SLAVE_SET_DOWNLOAD
import com.ejlchina.tool.util.COMMAND_485_SLAVE_SET_UPLOAD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_GET_DOWNWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_GET_UPWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_ALARM_SET_UPWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_GET_DOWNWARD
import com.ejlchina.tool.util.COMMAND_TEMPERATURE_GET_UPWARD
import com.ejlchina.tool.util.LOG_TAG
import com.ejlchina.tool.util.bytearray.intToByteHexString
import com.ejlchina.tool.util.bytearray.toHexString
import com.ejlchina.tool.util.showToast
import com.ejlchina.tool.view.HorizontalItemDecoration
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.huyuhui.fastble.data.BleDevice
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

const val BUNDLE_DEVICE_LIST = "BUNDLE_DEVICE_LIST"
class IndexFixFragment: BaseBindingFragment2<FragmentIndexFixBinding>() {

    private lateinit var bucketIndexAdapter: BucketIndexAdapter
    private val deviceListIndexFix = arrayListOf<BleDeviceBean>()
    private var howManyHasComplete = 0
    private var isHasFailResult = false
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initViews()
        initListeners()
        initObservers()
        initDeviceList()
        (requireActivity() as MainActivity).clearAllSaveData(2)
        getAllConnectDeviceCurrentTemperature()
        initVideo()
        getBucketIndexInfo()
    }

    private fun initViews(){
        setHeadTitle("桶序标定")
    }

    private fun initListeners(){
        binding.btnConfirm.setOnClickListener {
            howManyHasComplete = 0
            isHasFailResult = false
            deviceListIndexFix.forEach { bleDeviceBean ->
                if (!isHasFailResult) {
                    setBucketIndex(bleDeviceBean, bleDeviceBean.bucketNo)
                }
            }
        }

        binding.layoutIndexFixMode.tvBluetooth.setOnClickListener {
            switchMode(true)
            binding.layoutIndexFix.visibility = View.VISIBLE
            binding.layout485.visibility = View.GONE
            binding.btnConfirm.visibility = View.VISIBLE
            binding.detailPlayer.onVideoPause()
        }

        binding.layoutIndexFixMode.tv485.setOnClickListener {
            switchMode(false)
            binding.layoutIndexFix.visibility = View.GONE
            binding.layout485.visibility = View.VISIBLE
            binding.btnConfirm.visibility = View.GONE
            binding.detailPlayer.startPlayLogic()
        }
    }

    private fun initVideo(){
        binding.detailPlayer.apply {
            titleTextView.visibility = View.GONE
            backButton.visibility = View.GONE
            setUp(INDEX_FIX_URL,true,"")
            setIsTouchWiget(true)
            isNeedShowWifiTip = false
            isNeedOrientationUtils = false
            fullscreenButton.visibility = View.GONE
            isLooping = true
        }

    }

    private fun initObservers(){
        lifecycleScope.launch{
            repeatOnLifecycle(Lifecycle.State.STARTED){
                binding.tvConnectCount.text = viewModelActivity.getAllConnectDevicesCount().toString()
            }
        }
    }

    private fun getBucketIndexInfo(){
        showLoading()
        GlobalConnectObject.getCurrentConnectDeviceList().forEach {
            viewLifecycleOwner.lifecycleScope.launch {
                delay(COMMAND_DELAY_TIME_300)
                getBucketIndex(it)
            }
        }
    }

    private fun switchMode(isSelectBluetooth: Boolean){
        val selectBg =  R.drawable.shape_co_10_so_1f39ff_2
        val unselectBg = R.drawable.shape_co_10_so_f4f4f4
        val selectTvColor = Color.parseColor("#FFFFFF")
        val unselectTvColor = Color.parseColor("#2C2C2E")
        binding.layoutIndexFixMode.tvBluetooth.setBackgroundResource(if (isSelectBluetooth) selectBg else unselectBg)
        binding.layoutIndexFixMode.tvBluetooth.setTextColor(if (isSelectBluetooth) selectTvColor else unselectTvColor)
        binding.layoutIndexFixMode.tv485.setBackgroundResource(if (isSelectBluetooth) unselectBg else selectBg)
        binding.layoutIndexFixMode.tv485.setTextColor(if (isSelectBluetooth) unselectTvColor else selectTvColor)
    }

    private fun handleBucketInfoDataFromNet(bucketIndexList: List<BucketIndexInfo>){
        Log.i(LOG_TAG,"$bucketIndexList")
        deviceListIndexFix.forEach { bleDeviceBean ->
            val bucketIndexBean =  bucketIndexList.find { bucketIndexInfo -> bucketIndexInfo.mac == bleDeviceBean.bleDevice.mac }
            bucketIndexBean?.let {
                bleDeviceBean.deviceNo = it.deviceNo
                bleDeviceBean.bucketNo = it.bucketNo
            }
        }
        deviceListIndexFix.sortBy { it.bucketNo }
        bucketIndexAdapter.notifyDataSetChanged()
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun initDeviceList(){
        deviceListIndexFix.clear()
        deviceListIndexFix.addAll(GlobalConnectObject.getCurrentConnectDeviceList())
        bucketIndexAdapter = BucketIndexAdapter(deviceListIndexFix, bucketClick = { device,selectIndex ->

                if (selectIndex == -1){
                    (requireActivity() as MainActivity).restoreData(2)
                } else {
                    (requireActivity() as MainActivity).restoreDataExcept(2,deviceListIndexFix[selectIndex].bleDevice.mac)
                    setTurnOnLight(device)
                }

        }, indexClick = {clickIndex ->
            showBottom{ dialogIndex ->
                deviceListIndexFix[clickIndex].bucketNo = dialogIndex
                bucketIndexAdapter.notifyDataSetChanged()
                checkCanGoNext()
            }})
        binding.rvIndexFix.apply {
            layoutManager = LinearLayoutManager(requireContext())
            adapter = bucketIndexAdapter
            if (itemDecorationCount == 0){
                addItemDecoration(HorizontalItemDecoration())
            }
        }
    }


    private fun setBucketIndex(bleDevice: BleDeviceBean,index: Int){
        setCommandData(bleDevice,COMMAND_485_SLAVE_SET_DOWNLOAD, intToByteHexString(index + 127), writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
    }

    private fun getBucketIndex(bleDevice: BleDeviceBean){
        getCommandData(bleDevice, COMMAND_485_SLAVE_GET_DOWNLOAD)
    }

    private fun getAllConnectDeviceCurrentTemperature(){
        for (item in GlobalConnectObject.getCurrentConnectDeviceList()){
            getTemperatureAlarmData(item)
        }
    }

    private fun getCurrentTemperature(bleDevice: BleDeviceBean){
        getCommandData(bleDevice, COMMAND_TEMPERATURE_GET_DOWNWARD)
    }

    private fun setTurnOnLight(bleDevice: BleDeviceBean){
        val commandData = byteArrayOf(90.toByte(),80.toByte(),0.toByte(),89.toByte()).toHexString(false)
        setCommandData(bleDevice, COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD,commandData)
    }

    private fun setTurnOffLight(bleDevice: BleDeviceBean){
        val commandData = byteArrayOf(90.toByte(),(-20).toByte(),0.toByte(),89.toByte()).toHexString(false)
        setCommandData(bleDevice, COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD,commandData)
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun whenDeviceDisConnect(disConnectDevice: BleDevice) {
        super.whenDeviceDisConnect(disConnectDevice)
        if (isAdded){
            binding.tvConnectCount.text = viewModelActivity.getAllConnectDevicesCount().toString()
        }
        deviceListIndexFix.removeIf { it.bleDevice.mac == disConnectDevice.mac }
        bucketIndexAdapter.notifyDataSetChanged()
    }

    @OptIn(ExperimentalStdlibApi::class)
    override fun whenReceiveCommand(bleDevice: BleDeviceBean, command: String, dataByteArray: ByteArray) {
        super.whenReceiveCommand(bleDevice, command, dataByteArray)
        when (command) {

            COMMAND_485_SLAVE_GET_UPWARD -> {
                deviceListIndexFix.find { it.bleDevice.mac == bleDevice.bleDevice.mac }?.let { bleDeviceBean ->
                    bleDeviceBean.bucketNo = dataByteArray[0].toHexString().toInt() - 79
                    bucketIndexAdapter.notifyDataSetChanged()
                    howManyHasComplete++
                    if (howManyHasComplete >= GlobalConnectObject.getCurrentConnectDeviceList().size) {
                        checkCanGoNext()
                        dismissLoading()
                    }
                }
            }

            COMMAND_TEMPERATURE_GET_UPWARD -> {
                deviceListIndexFix.find { it.bleDevice == bleDevice.bleDevice }?.let {
                    it.isOpenLight = dataByteArray[0].toInt() != 0
                }
                getTemperatureAlarmData(bleDevice)
            }

            COMMAND_TEMPERATURE_ALARM_GET_UPWARD -> {
                (requireActivity() as MainActivity).saveData(
                    2,
                    bleDevice.bleDevice,
                    COMMAND_TEMPERATURE_ALARM_SET_DOWNLOAD,
                    dataByteArray.toHexString(false)
                )
            }

            COMMAND_TEMPERATURE_ALARM_SET_UPWARD -> {
                dismissLoading()
                if (dataByteArray[dataByteArray.size - 1].toInt() == SuccessFailEnum.SUCCESS.value) {
                    deviceListIndexFix.find { bleDeviceBean -> bleDeviceBean.bleDevice == bleDevice.bleDevice }?.let {
                        it.isOpenLight = !it.isOpenLight
                        bucketIndexAdapter.notifyDataSetChanged()
                    }
                }
            }

            COMMAND_485_SLAVE_SET_UPLOAD -> {
                if (dataByteArray[dataByteArray.size - 1].toInt() == SuccessFailEnum.SUCCESS.value) {
                    howManyHasComplete++
                    updateConnectList()
                        GlobalConnectObject.getCurrentConnectDeviceList().sortBy { it.bucketNo }
                        if (howManyHasComplete >= deviceListIndexFix.size) {
                            showToast("设置成功")
                            dismissLoading()
                            findNavController().safeNavigate(R.id.action_global_configFragment)
                        }
//                    }
                } else {
                    isHasFailResult = true
                    showToast("设置失败")
                }
            }
        }
    }

    private fun updateConnectList(){
        val itCurrentConnectList: MutableIterator<BleDeviceBean> = GlobalConnectObject.getCurrentConnectDeviceList().iterator()
        while (itCurrentConnectList.hasNext()) {
            val connectDevice = itCurrentConnectList.next()
            deviceListIndexFix.find { it.bleDevice.mac == connectDevice.bleDevice.mac }?.let { findDevice ->
                connectDevice.bucketNo = findDevice.bucketNo
            }
        }
    }

    private fun getTemperatureAlarmData(bleDevice: BleDeviceBean){
        getCommandData(bleDevice, COMMAND_TEMPERATURE_ALARM_GET_DOWNWARD)
    }

    private fun showBottom(clickCallback: (Int) -> Unit){
        val indexFixDialogAdapter = IndexFixDialogAdapter(getBottomDialogList())
        val layoutBinding = DialogIndexFixSelectIndexBinding.inflate(LayoutInflater.from(binding.root.context),null,false)
        val bottomSheetDialog = BottomSheetDialog(binding.root.context, R.style.bottom_sheet_dialog)
        layoutBinding.recyclerView.apply {
            adapter = indexFixDialogAdapter
            layoutManager = LinearLayoutManager(binding.root.context)
        }
        layoutBinding.tvCancel.setOnClickListener {
            bottomSheetDialog.dismiss()
        }
        layoutBinding.tvConfirm.setOnClickListener {
            clickCallback(indexFixDialogAdapter.getSelectIndex())
            bottomSheetDialog.dismiss()
        }
        bottomSheetDialog.setContentView(layoutBinding.root)
        bottomSheetDialog.show()
    }

    private fun checkCanGoNext(){
        val isAllDeviceIndexed = deviceListIndexFix.all { it.bucketNo != -1 }
        val resId = if (isAllDeviceIndexed) R.drawable.ripple_co_11_so_1f39ff else R.drawable.shape_co_11_so_d5daff
        binding.btnConfirm.isEnabled = isAllDeviceIndexed
        binding.btnConfirm.setBackgroundResource(resId)
    }

    private fun getBottomDialogList(): List<Int>{
        val bottomDialogList = arrayListOf(-1)
        val deviceIndexList = deviceListIndexFix.map { it.bucketNo }
        for (item in (1 .. 10)){
            bottomDialogList.add(item)
        }
//        deviceIndexList.forEach {
//            if (it != -1){  //-1表示未设置
//                bottomDialogList.remove(it)
//            }
//        }
        return bottomDialogList
    }

    override fun getViewBinding(inflater: LayoutInflater, container: ViewGroup): FragmentIndexFixBinding {
        return FragmentIndexFixBinding.inflate(inflater,container,true)
    }

    override fun onDestroyView() {
        (requireActivity() as MainActivity).restoreData(2)
        (requireActivity() as MainActivity).clearAllSaveData(2)
        binding.detailPlayer.onVideoPause()
        super.onDestroyView()
    }
}